package edu.pku.sei.mte.mtemodel.mtmodel.expression;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import edu.pku.sei.mte.constants.MDAConstant;
import edu.pku.sei.mte.runtime.Context;
import edu.pku.sei.mte.utilities.Visitor;

public class InvokeMethodExpression extends Expression {
	
	
	private List<Expression> parameters = new ArrayList<Expression>();
	private Expression caller;
	private String methodName;
	
	public void addParameter(Expression e){
		parameters.add(e);
	}

	@SuppressWarnings("unchecked")
	public Object evaluate(Context context, boolean enforce) {
		Object callerInstance = caller.evaluate(context, false);
		Class cls = callerInstance.getClass();
		
		Class[] paras = new Class[parameters.size()];
		Object[] args = new Object[parameters.size()];
		
		int i=0,s=parameters.size();
		
		for(i=0;i<s;i++){
			Expression pe = parameters.get(i);
			Object pi = pe.evaluate(context, false);
			paras[i]=pi.getClass();
			args[i]=pi;
		}
		
		try {
			Method m = cls.getMethod(methodName, paras);
			Object ret = m.invoke(callerInstance, args);
			return ret;
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
		} catch (IllegalArgumentException e) {
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		}
		return Boolean.FALSE;
	}

	public Object evaluate(Context context, boolean enforce,
			Object expectedValue) {
		return MDAConstant.ERROR_VALUE;
	}

	public void collectReferedProperty(String root, List<String> coll) {
	}

	public void setCaller(Expression caller) {
		this.caller = caller;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
	
	@Override
	public Object accept(Visitor visitor) throws Exception {
		return visitor.visitInvokeMethodExpression(this);
	}

	public Expression getCaller() {
		return caller;
	}

	public String getMethodName() {
		return methodName;
	}

	public List<Expression> getParameters() {
		return parameters;
	}
}
